#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Icon=favicon.ico
#AutoIt3Wrapper_Compression=4
#AutoIt3Wrapper_Res_Description=Vipre Scanner Script
#AutoIt3Wrapper_Res_Fileversion=0.6.0.5
#AutoIt3Wrapper_Res_FileVersion_AutoIncrement=y
#AutoIt3Wrapper_Res_LegalCopyright=John Seekins
#AutoIt3Wrapper_Res_SaveSource=y
#AutoIt3Wrapper_Res_Language=1033
#AutoIt3Wrapper_res_requestedExecutionLevel=requireAdministrator
#AutoIt3Wrapper_Res_Icon_Add=favicon.ico
#AutoIt3Wrapper_Run_Tidy=y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#comments-start
	Copyright (c) <2011>, <John Seekins>
	All rights reserved.
	
	Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
	
	* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
	* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
	* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
	
	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#comments-end
#Region Include Statements
#include <GUIConstants.au3>
#include <File.au3>
#include <string.au3>
#EndRegion Include Statements

Opt("TrayIconHide", 1)
Opt("GUICloseOnESC", 0)
Opt("GUICoordMode", 1)

#Region Variable Declarations
Const $DeleteVipreDataSwitch = "/deleteVipreData"
Const $PermissionsRepairSwitch = "/permScan"
Const $StartupScannerSwitch = "/startupScan"
Const $noPreGUIScannerSwitch = "/noPreGuiScan"
Const $displayProgramLogSwitch = "/displayLog"
Const $programTitle = "Vipre Scanner GUI"
Const $iniFileName = @ScriptDir & "\vpr_dat.ini"
Const $processListFile = @ScriptDir & "\processlist.ini"
Const $systemDrive = StringLeft(@SystemDir, 3)
Global $vipreDirectory = $systemDrive & IniRead($iniFileName, "Global", "VipreDirectory", "VIPRERescue")
Global $vipreProgramName = IniRead($iniFileName, "Global", "VipreProgramName", "VRS.exe")
Global $vipreGUIName = IniRead($iniFileName, "Global", "VipreGUIName", "VipreScanner.exe")
If FileExists($processListFile) Then
	Global $windowsProcesses = IniReadSection($processListFile, "Windows Process")
	Global $viralProcesses = IniReadSection($processListFile, "Viral Processes")
	Global $proccessListWait = IniRead($processListFile, "General", "Wait", 3000)
EndIf
$msg = ""
$logFileSearch = ""
$logFileName = ""
$reboot = 1
$BaseX = 20
$BaseY = 15
$CurX = 0
$CurY = 0
$vipreRunScript = ""
$preGuiMessage = ""
#EndRegion Variable Declarations

$hGUI = GUICreate($programTitle, 215, 200)

#Region Drop-Down Menu
$fileMenu = GUICtrlCreateMenu("&File")
$updateVipreMenuItem = GUICtrlCreateMenuItem("&Update", $fileMenu)
$exitProgramMenuItem = GUICtrlCreateMenuItem("E&xit", $fileMenu)
$helpMenu = GUICtrlCreateMenu("&Help")
$aboutMenuItem = GUICtrlCreateMenuItem("About...", $helpMenu)
#EndRegion Drop-Down Menu

#Region Create GUI
$CurX = $BaseX
$CurY = $BaseY
GUICtrlCreateLabel("Post-Scan Options:", $CurX, $CurY)
$CurY += 35
$hBootScanCheckBox = GUICtrlCreateCheckbox("Run a Boot-Time Scan?", $CurX, $CurY)
$CurY += 35
$hPermCheckBox = GUICtrlCreateCheckbox("Scan/Repair Security Permissions?", $CurX, $CurY)
$CurY += 40
$CurX += 55
$executeButton = GUICtrlCreateButton("Scan!", $CurX, $CurY)
#EndRegion Create GUI

#Region Pre-GUI Setup
#cs
	1) kill any processes in the processlist.ini file
	2) parse any command line switches passed into Vipre
	3) copy data from temp directory to root of system drive
#ce
If IsArray($windowsProcesses) And IsArray($viralProcesses) Then
	For $i = 1 To $windowsProcesses[0][0]
		ProcessClose($windowsProcesses[$i][1])
	Next
	For $i = 1 To $viralProcesses[0][0]
		ProcessClose($viralProcesses[$i][1])
	Next
EndIf

;if there are command line switches...
If $CmdLine[0] <> 0 Then
	For $i = 1 To $CmdLine[0]
		Switch $CmdLine[$i]
			Case $StartupScannerSwitch
				$PID = Run($vipreDirectory & "\" & $vipreProgramName & " /norootkit /quick /nolog", $vipreDirectory, @SW_MAXIMIZE)
				stopProcesses($PID)
				$msg = $GUI_EVENT_CLOSE
			Case $PermissionsRepairSwitch
				permRepair()
				$msg = $GUI_EVENT_CLOSE
			Case $displayProgramLogSwitch
				displayThreats()
				$msg = $GUI_EVENT_CLOSE
			Case $DeleteVipreDataSwitch
				;remove Vipre services from the machine.  Data in the $vipreDirectory folder is retained for more analysis or false positive recovery
				FileDelete(@SystemDir & "\Drivers\SBREDrv.sys")
				FileDelete(@SystemDir & "sbbd.exe")
				RegDelete("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\SBRE")
				RegDelete("HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\SBRE")
				RegDelete("HKEY_LOCAL_MACHINE\SYSTEM\ControlSet002\Services\SBRE")
				RegDelete("HKEY_LOCAL_MACHINE\SYSTEM\ControlSet003\Services\SBRE")
				MsgBox(48, "Vipre Scanner Removal", "Remenants of this program are stored in " & $vipreDirectory & @LF & _
						"Please remove them after any further work.")
				$msg = $GUI_EVENT_CLOSE
			Case $noPreGUIScannerSwitch
				GUISetState()
				;permission checks can be improperly recreated if a domain member has the permission repairs run when not on the domain.
				GUICtrlSetState($hPermCheckBox, $GUI_CHECKED)
				GUICtrlSetState($hBootScanCheckBox, $GUI_CHECKED)
			Case Else
				MsgBox(64, "Bad Command Line Switch!", "The command line switch you provided, " & $CmdLine[$i] & ", is invalid for this program.", 10)
		EndSwitch
	Next
	; otherwise, build the regular GUI
Else
	ProgressOn("Preparing to run Vipre Rescue Scanner...", "Configuring Vipre Scanner...", "", -1, -1, 16)
	ProgressSet(10, "Creating Vipre Directory")
	DirCreate($vipreDirectory)
	ProgressSet(40, "Copying Data to Vipre Directory")
	DirCopy(@ScriptDir, $vipreDirectory, 1)
	ProgressSet(55, "Configuring Vipre Drivers")
	If StringCompare(@CPUArch, "X86") = 0 Then
		FileCopy($vipreDirectory & "\SBREDrv.sys", @SystemDir & "\Drivers", 1)
		ProgressSet(60)
		FileCopy($vipreDirectory & "\sbbd.exe", @SystemDir, 1)
	Else
		FileCopy($vipreDirectory & "\x64\SBREDrv.sys", @SystemDir & "\Drivers", 1)
		ProgressSet(60)
		FileCopy($vipreDirectory & "\x64\sbbd.exe", @SystemDir, 1)
	EndIf
	ProgressSet(70, "", "Pre-Vipre Malware Scans")
	$preGuiMessage = preGuiScans()
	ProgressOff()

	If StringCompare($preGuiMessage, "") = 0 Then
		GUISetState()
		GUICtrlSetState($hPermCheckBox, $GUI_CHECKED)
		GUICtrlSetState($hBootScanCheckBox, $GUI_CHECKED)
	Else
		RegWrite("HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnce", "BootUpVipre", "REG_EXPAND_SZ", $vipreDirectory & "\" _
				 & $vipreGUIName & " " & $noPreGUIScannerSwitch)
		MsgBox(16, "Malware Activity Discovered!", $preGuiMessage & @LF & "Will reboot in 10 seconds...", 10)
		$msg = $GUI_EVENT_CLOSE
	EndIf
EndIf
#EndRegion Pre-GUI Setup

While $msg <> $GUI_EVENT_CLOSE
	For $i = 1 To $windowsProcesses[0][0]
		ProcessClose($windowsProcesses[$i][1])
	Next
	For $i = 1 To $viralProcesses[0][0]
		ProcessClose($viralProcesses[$i][1])
	Next

	$msg = GUIGetMsg()

	Switch $msg ;user actions are stored in $msg, parse possible reactions here:
		Case $aboutMenuItem
			MsgBox(64, $programTitle, "Version: " & FileGetVersion($vipreGUIName) & @LF & "7-zip obtained from www.7-zip.org/" & @LF & _
					"wget for Windows obtained from http://gnuwin32.sourceforge.net/packages/wget.htm" & @LF & _
					"subinacl.exe obtained from www.microsoft.com" & @LF & _
					"And of course, the Vipre Rescue Scanner is property of Sunbelt Software at http://www.sunbeltsoftware.com/")

		Case $exitProgramMenuItem
			$msg = $GUI_EVENT_CLOSE
			$reboot = 0

		Case $executeButton
			modCallingWindow($programTitle, @SW_MINIMIZE)
			;post-boot scans...
			;based on the selections of the user, add any post-reboot scans they asked for into the RunOnce key and execute them...
			$postBoot = $vipreDirectory & "\" & $vipreGUIName
			If GUICtrlRead($hBootScanCheckBox) = $GUI_CHECKED Then $postBoot &= " " & $StartupScannerSwitch

			If GUICtrlRead($hPermCheckBox) = $GUI_CHECKED Then $postBoot &= " " & $PermissionsRepairSwitch

			$postBoot &= " " & $displayProgramLogSwitch & " " & $DeleteVipreDataSwitch
			RegWrite("HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnce", "BootUpVipre", "REG_EXPAND_SZ", $postBoot)
			;end post-boot scans...

			ProgressOn("Vipre Command Line Virus Scanner", "", "", -1, -1, 16)
			ProgressSet(20, "", "Cleaning temporary files...")
			DirRemove(@WindowsDir & "\Temp", 1)
			DirCreate(@WindowsDir & "\Temp")
			DirRemove(@TempDir, 1)
			DirCreate(@TempDir)
			;this appears to simply corrupt the recycle bin, but it should actually dump the data, so...
			FileRecycleEmpty($systemDrive)

			ProgressSet(30, "", "Scanning for Viruses...")
			$vipreRunScript = $vipreDirectory & "\" & $vipreProgramName
			$PID = Run($vipreRunScript, $vipreDirectory, @SW_MAXIMIZE)
			stopProcesses($PID)

			ProgressSet(69, "", "Copying log file to " & $systemDrive)
			$logFileSearch = FileFindFirstFile($vipreDirectory & "\*.xml")
			;find xml files until you find one who's name (sans the .xml) is entirely made up of numbers
			;this is the current format for Vipre log files
			Do
				$logFileName = FileFindNextFile($logFileSearch)
				If @error Then ExitLoop
			Until StringIsDigit(StringLeft($logFileName, StringLen($logFileName) - 4)) <> 0
			FileClose($logFileSearch)
			If StringCompare($logFileName, "") <> 0 Then FileCopy($vipreDirectory & "\" & $logFileName, $systemDrive & "VipreLog.xml", 1)

			ProgressOff()
			MsgBox(64, "Machine Restarting...", "The machine will restart in 10 seconds...", 10)
			$msg = $GUI_EVENT_CLOSE

		Case $updateVipreMenuItem
			$vipreProgramName = updateVipre()
	EndSwitch
WEnd
GUIDelete()
If $reboot <> 0 Then Shutdown(2)

;$PID contains the process id to monitor
;essentially, when that process is done, we can stop killing these other processes
Func stopProcesses($PID)
	If IsArray($windowsProcesses) And IsArray($viralProcesses) Then
		;		For $i = 1 To $windowsProcesses[0][0]
		;			ProcessClose($windowsProcesses[$i][1])
		;		Next
		;		For $i = 1 To $viralProcesses[0][0]
		;			ProcessClose($viralProcesses[$i][1])
		;		Next
		While ProcessExists($PID) <> 0
			Sleep($proccessListWait)
			For $i = 1 To $windowsProcesses[0][0]
				ProcessClose($windowsProcesses[$i][1])
			Next
			For $i = 1 To $viralProcesses[0][0]
				ProcessClose($viralProcesses[$i][1])
			Next
		WEnd
	EndIf
EndFunc   ;==>stopProcesses

;adding other scanners here is not difficult
Func preGuiScans()
	Local $line = ""
	Local $tempLine = ""
	Local $fileHandle = ""
	Local $testOK = 0
	Local $return = ""
	Dim $preGuiScanMessages[4]
	$preGuiScanMessages[0] = "No Rootkits found with catchme and mbr scans..."
	$preGuiScanMessages[1] = "Malware removed with Microsoft's Malicious Software Removal Tool"

	If FileExists(@WindowsDir & "\Debug\mrt.log") Then FileDelete(@WindowsDir & "\Debug\mrt.log")

	ProgressSet(85, "Scanning with Microsoft's MRT...")
	If FileExists(@SystemDir & "\mrt.exe") Then
		$PID = Run(@SystemDir & "\mrt.exe /Q", @SystemDir, @SW_SHOW)
		stopProcesses($PID)

		#Region MRT log parsing
		;MRT displays a return code at the end of each run in it's log file (located at %windir%\debug\mrt.log)
		;if there are no infections found, it returns 0
		;if there is a program error, returns run from 1 to 5
		;infections are returns 6 to 13
		$fileHandle = FileOpen(@WindowsDir & "\Debug\mrt.log", 0)
		While 1
			$line = FileReadLine($fileHandle)
			If @error Then ExitLoop
			If StringInStr($line, "Return code:") <> 0 Then
				$line = StringTrimLeft($line, 13)
				$line = StringTrimRight($line, 6)
				If StringIsInt($line) Then
					Switch $line
						Case 0 To 5
							$testOK = 1
						Case 6 To 13
							$testOK = 0
					EndSwitch
				EndIf
			EndIf
		WEnd
		FileClose($fileHandle)
		#EndRegion MRT log parsing
		If Not $testOK Then $return = $preGuiScanMessages[1]
	EndIf
	Return $return
EndFunc   ;==>preGuiScans

Func permRepair()
	Local $rc = 0
	ProgressOn("Command Line Permissions Repair", "", "", -1, -1, 16)
	ProgressSet(14, "Repairing " & $systemDrive & " ACL permissions...", "Repairing security permissions...")
	$rc = Run($vipreDirectory & "\subinacl.exe /errorlog=" & $vipreDirectory & "\subinacldrive.log /subdirectories " & $systemDrive & " /grant=administrators=f /grant=system=f", "", @SW_SHOW)
	stopProcesses($rc)
	ProgressSet(28, "Repairing " & @WindowsDir & " ACL permissions...")
	$rc = Run($vipreDirectory & "\subinacl.exe /errorlog=" & $vipreDirectory & "\subinaclWinDir.log /subdirectories " & @WindowsDir & "\*.* /grant=administrators=f /grant=system=f", "", @SW_SHOW)
	stopProcesses($rc)
	If StringCompare(@OSVersion, "WIN_2008") = 0 Or StringCompare(@OSVersion, "WIN_VISTA") = 0 Or StringCompare(@OSVersion, "WIN_7") = 0 Then
		ProgressSet(56, "Repairing " & @WindowsDir & " security permissions")
		$rc = Run(@SystemDir & "\secedit.exe /configure /cfg " & @WindowsDir & "\inf\defltbase.inf /db defltbase.sdb /verbose > " & $vipreDirectory & "\secedit.log", "", @SW_SHOW)
		stopProcesses($rc)
	Else
		$analyze = @SystemDir & "\secedit.exe /analyze /db " & @WindowsDir & "\sectest.db /cfg " & @WindowsDir & "\inf\defltwk.inf /log " & $vipreDirectory & "\secanalyze.log"
		$configure = @SystemDir & "\secedit.exe /configure /db " & @WindowsDir & "\sectest.db /cfg " & @WindowsDir & "\inf\defltwk.inf /log " & $vipreDirectory & "\secrepair.log"
		ProgressSet(42, "Analyzing " & @WindowsDir & " security permissions...")
		$rc = Run($analyze, "", @SW_SHOW)
		stopProcesses($rc)
		ProgressSet(56, "Repairing " & @WindowsDir & " security permissions...")
		$rc = Run($configure, "", @SW_SHOW)
		stopProcesses($rc)
	EndIf
	ProgressSet(70, "Repairing HKLM ACL permissions...")
	$rc = Run($vipreDirectory & "\subinacl.exe /errorlog=" & $vipreDirectory & "\subinaclHKLM.log /subkeyreg HKEY_LOCAL_MACHINE /grant=administrators=f /grant=system=f", "", @SW_SHOW)
	stopProcesses($rc)
	ProgressSet(84, "Repairing HK_CURRENT_USER ACL permissions...")
	$rc = Run($vipreDirectory & "\subinacl.exe /errorlog=" & $vipreDirectory & "\subinaclHCU.log /subkeyreg HKEY_CURRENT_USER /grant=administrators=f /grant=system=f", "", @SW_SHOW)
	stopProcesses($rc)
	ProgressSet(96, "repairing HK_CLASSES_ROOT ACL permissions...")
	$rc = Run($vipreDirectory & "\subinacl.exe /errorlog=" & $vipreDirectory & "\subinaclHCR.log /subkeyreg HKEY_CLASSES_ROOT /grant=administrators=f /grant=system=f", "", @SW_SHOW)
	stopProcesses($rc)
	ProgressOff()
EndFunc   ;==>permRepair

Func IsVisible($handle)
	If BitAND(WinGetState($handle), 2) Then
		Return 1
	Else
		Return 0
	EndIf
EndFunc   ;==>IsVisible

Func modCallingWindow($title, $state)
	Local $activeWindowList = WinList()
	Local $windowNumber = 0
	For $i = 1 To $activeWindowList[0][0]
		If $activeWindowList[$i][0] <> "" And IsVisible($activeWindowList[$i][1]) Then
			Local $windowTitle = StringTrimLeft($activeWindowList[$i][0], StringLen($activeWindowList[$i][0]) - StringLen($title))
			If $windowTitle = $title Then
				$windowNumber = $i
				WinSetState($activeWindowList[$i][0], "", $state)
			EndIf
		EndIf
	Next
EndFunc   ;==>modCallingWindow

Func updateVipre()
	Local $rc = 0
	Local $vNewProgName = _TempFile($vipreDirectory, "vpr_", ".exe")
	$vNewProgName = StringRight($vNewProgName, StringLen($vNewProgName) - StringInStr($vNewProgName, "\vpr_"))
	If FileExists($vipreDirectory & "\SBRE.dll") Then DirRemove($vipreDirectory & "\Definitions", 1)
	modCallingWindow($programTitle, @SW_MINIMIZE)
	ProgressOn("Updating Vipre Rescue Scanner...", "This will take some time...", "Downloading from Sunbeltsoftware.com", -1, -1, 16)
	$rc = Run($vipreDirectory & "\wget.exe http://live.sunbeltsoftware.com/download --output-document=VIPREOrig.exe", $vipreDirectory, @SW_SHOW)
	stopProcesses($rc)
	ProgressSet(50, "Extracting data...")
	$rc = Run($vipreDirectory & "\7z.exe x -y VIPREOrig.exe", $vipreDirectory, @SW_SHOW)
	stopProcesses($rc)
	ProgressSet(90, "Configuring files...")
	FileDelete($vipreDirectory & "\VIPREOrig.exe")
	FileDelete($vipreDirectory & "\deep_scan.bat")
	FileDelete($vipreDirectory & "\" & $vipreProgramName)
	FileCopy($vipreDirectory & "\VipreRescueScanner.exe", $vipreDirectory & "\" & $vNewProgName)
	FileDelete($vipreDirectory & "\VipreRescueScanner.exe")
	If StringCompare(@CPUArch, "X86") = 0 Then
		FileCopy($vipreDirectory & "\SBREDrv.sys", @SystemDir & "\Drivers", 1)
		ProgressSet(92)
		FileCopy($vipreDirectory & "\sbbd.exe", @SystemDir, 1)
	Else
		FileCopy($vipreDirectory & "\x64\SBREDrv.sys", @SystemDir & "\Drivers", 1)
		ProgressSet(92)
		FileCopy($vipreDirectory & "\x64\sbbd.exe", @SystemDir, 1)
	EndIf
	IniWrite($iniFileName, "Global", "VipreProgramName", $vNewProgName)
	ProgressOff()
	modCallingWindow($programTitle, @SW_RESTORE)
	MsgBox(64, "Updated Successfully", "Successfully updated virus scanner and definiitions...", 10)
	Return $vNewProgName
EndFunc   ;==>updateVipre

#Region XML Processing
Func displayThreats()
	#Region Variable Declarations
	Local $numThreatsString = "numThreats "
	Local $numTracesString = "numTracesFound"
	Local $ThreatsFoundString = ""
	Local $TracesFoundString = ""
	Local $ThreatNumberArray = ""
	Local $TracesNumberArray = ""
	Local $ThreatDescripArray = ""
	Local $TracesDescripArray = ""
	#EndRegion Variable Declarations

	If Not FileExists($systemDrive & "VipreLog.xml") Then
		MsgBox(16, "Missing Log File", "No log file found...cannot display results.")
	Else
		$fileHandle = FileOpen($systemDrive & "VipreLog.xml", 0)

		$currentLine = FileReadLine($fileHandle)
		FileClose($fileHandle)
		$currentLine = _StringExplode($currentLine, "<")

		$ThreatsFoundString = StringTrimLeft(findStringFrom1DArray($currentLine, $numThreatsString & "deleted"), StringLen($numThreatsString))
		$TracesFoundString = StringTrimLeft(findStringFrom1DArray($currentLine, $numTracesString), StringLen($numTracesString))

		$ThreatNumberArray = StringSplit(stringStripAlpha($ThreatsFoundString), " ")
		$TracesNumberArray = StringSplit(stringStripAlpha($TracesFoundString), " ")
		$ThreatDescripArray = StringSplit(stringMakeAlpha($ThreatsFoundString), " ")
		$TracesDescripArray = StringSplit(stringMakeAlpha($TracesFoundString), " ")

		$ThreatsFoundString = ""
		$TracesFoundString = ""
		For $i = 1 To $ThreatNumberArray[0]
			$ThreatsFoundString &= $ThreatDescripArray[$i] & " = " & $ThreatNumberArray[$i] & @LF
		Next
		For $i = 1 To $TracesNumberArray[0]
			$TracesFoundString &= $TracesDescripArray[$i] & " = " & $TracesNumberArray[$i] & @LF
		Next
		$TracesFoundString &= "Further information can be found in " & $systemDrive & "VipreLog.xml"
		$ThreatsFoundString &= "Further information can be found in " & $systemDrive & "VipreLog.xml"
		MsgBox(0, "Viral And Spyware Threats On Machine", $ThreatsFoundString)
		MsgBox(0, "Viral And Spyware Traces On Machine", $TracesFoundString)
		If GUICtrlRead($hPermCheckBox) = $GUI_CHECKED Then MsgBox(0, "Security and ACL Scans", "Performed Security and ACL scans and repairs." & @LF & "Results stored in " & $vipreDirectory)
	EndIf
EndFunc   ;==>displayThreats

#cs ----------------
	returns the string from the array containing the search string
#ce ----------------
Func findStringFrom1DArray($searchList, $searchString)
	$stringPos = 0
	For $i = 1 To UBound($searchList) - 1
		$stringPos = StringInStr($searchList[$i], $searchString)
		If $stringPos <> 0 Then Return $searchList[$i]
	Next
	Return ""
EndFunc   ;==>findStringFrom1DArray

#cs ---------------------
	pull one character at a time from the string...
	if it's a digit [0-9], start adding every character from that digit on
	until the character to add is not a digit.  Then add a space at the end.
	This essentially makes the following string:
	error action="1" item="C:\Documents and Settings\LocalService\Local Settings\Application Data\Microsoft\Windows\UsrClass.dat" code="32" time="2009-07-21T21:22:17" />
	into:
	1 32 2009 07 21 21 22 17
#ce ---------------------
Func stringStripAlpha($alphNumString)
	$tempString = ""
	$numberString = ""
	For $i = 1 To StringLen($alphNumString)
		$tempString = StringMid($alphNumString, $i, 1)
		If StringIsDigit($tempString) Then
			#cs ---------------------
				we need to add each digit onto the actual number as it appears in the string
				so the final string has each number listed individually.
				this do loop adds those extra digits if they're there
				also, some lines can have a entry like number3="4" or 3number="4".  We don't want the three
				there to be considered a number, so we'll skip it if the characters directly
				proceeding or following the number are letters (alpha characters)
			#ce ----------------------
			Do
				If (Not StringIsAlpha(StringMid($alphNumString, $i - 1, 1))) And (Not StringIsAlpha(StringMid($alphNumString, $i + 1, 1))) Then
					$numberString &= $tempString
				EndIf
				$i += 1
				$tempString = StringMid($alphNumString, $i, 1)
			Until Not StringIsDigit($tempString)
			$numberString &= " "
		EndIf
	Next
	$numberString = StringReplace($numberString, "  ", " ")
	;remove the trailing space
	Return StringTrimRight($numberString, 1)
EndFunc   ;==>stringStripAlpha

#cs ---------------------
	Very similar to stringStripAlpha except we're dumping everything but each
	individual word in the string, i.e.
	error action="1" item="C:\Documents and Settings\LocalService\Local Settings\Application Data\Microsoft\Windows\UsrClass.dat" code="32" time="2009-07-21T21:22:17" />
	becomes:
	error action item C Documents and Settings LocalService Local Settings Application Data Microsoft Windows UsrClass dat code time
	Note:
	Numbers that end the string (i.e. number3 or test100) will be attached to the word
	Numbers that start a string (i.e. 3number or 100test) currently do not get attached
#ce ---------------------
Func stringMakeAlpha($alphNumString)
	$tempString = ""
	$alphaString = ""
	For $i = 1 To StringLen($alphNumString)
		$tempString = StringMid($alphNumString, $i, 1)
		If StringIsAlpha($tempString) Then
			Do
				$alphaString &= $tempString
				$i += 1
				$tempString = StringMid($alphNumString, $i, 1)
			Until Not StringIsAlpha($tempString)
			If StringIsDigit($tempString) Then
				Do
					$alphaString &= $tempString
					$i += 1
					$tempString = StringMid($alphNumString, $i, 1)
				Until Not StringIsDigit($tempString)
			EndIf
			$alphaString &= " "
		EndIf
	Next
	Return StringTrimRight($alphaString, 1)
EndFunc   ;==>stringMakeAlpha
#EndRegion XML Processing